Introducción

De acuerdo con Google “la pestaña de tendencias de YouTube permite que los usuarios descubran las novedades de YouTube” [1]. Esta es una lista común compuesta de videos actuales que se muestra a todos los usuarios de un mismo país. YouTube mantiene listas de tendencias diferentes para cada país, las cuales actualiza con una frecuencia de 15 minutos. Si bien Google no ha hecho público el método para calcular las listas de tendencias, ha comunicado que buscan seleccionar videos que representen la actualidad de YouTube y sean relevantes para los usuarios del país correspondiente. Algunos de los factores que tienen en cuenta son:

En base a estos criterios, es posible que se encuentren videos con bajas visitas en posiciones altas de la lista, si estas se comparan con otros videos de la misma lista.

El conjunto de datos seleccionado, YouTube Trending Video Dataset (updated daily) contiene la información de estas listas de tendencias de 11 países: Brasil, Canadá, Alemania, Francia, Gran Bretaña, India, Japón, Corea del sur, México, Rusia y Estados Unidos. Algunos de los datos que incluye son el título del video, la fecha de subida del video, la cantidad de likes y de visitas, etc. El conjunto de datos es actualizado con una frecuencia diaria y se agregan hasta 200 videos nuevos en las listas de tendencias por día. Se utilizará la versión 610 del conjunto de datos, la cual contiene datos actualizados hasta el día 7 de Abril de 2022.

El creador de este conjunto de datos propone algunos usos:

Añadiendo a estas propuestas, puede resultar interesante el estudio de estos datos para encontrar todo tipo de relaciones entre los datos de cada video y el entorno de YouTube, por ejemplo:

Otra área que resulta interesante explorar es automatizar la generación de alguno de los atributos del conjunto de datos, como la miniatura, el título o la descripción. Finalmente, la predicción del rendimiento de un video (visualizaciones, likes, dislikes) es otra razón que hace interesante el estudio de este conjunto de datos.

Análisis exploratorio del conjunto de datos

Los datos a analizar corresponden a los trendings de YouTube para el país de México, separado en dos dataset, uno que corresponde al principal, y un segundo dataset con información de las categorías disponibles para cada video.

Se comenzará cargando el dataset principal a un dataframe:

mx_dataset <- read.csv("./dataset/MX_youtube_trending_data.csv", encoding = "UTF-8")
head(mx_dataset, n = 20)

Las dimensiones del dataset son, 121.399 filas y 16 columnas.

dim(mx_dataset)
## [1] 121399     16

Una versión resumida del dataset se encuentra a continuación, en este resumen se indican:

summary(mx_dataset)
##    video_id            title           publishedAt         channelId        
##  Length:121399      Length:121399      Length:121399      Length:121399     
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  channelTitle         categoryId    trending_date          tags          
##  Length:121399      Min.   : 1.00   Length:121399      Length:121399     
##  Class :character   1st Qu.:10.00   Class :character   Class :character  
##  Mode  :character   Median :22.00   Mode  :character   Mode  :character  
##                     Mean   :18.69                                        
##                     3rd Qu.:24.00                                        
##                     Max.   :29.00                                        
##    view_count            likes             dislikes      comment_count    
##  Min.   :        0   Min.   :       0   Min.   :     0   Min.   :      0  
##  1st Qu.:   378754   1st Qu.:   19048   1st Qu.:   123   1st Qu.:    898  
##  Median :   850201   Median :   53161   Median :   546   Median :   2289  
##  Mean   :  2249624   Mean   :  160530   Mean   :  2323   Mean   :  11988  
##  3rd Qu.:  2089202   3rd Qu.:  146047   3rd Qu.:  1712   3rd Qu.:   6136  
##  Max.   :278080610   Max.   :16213758   Max.   :879359   Max.   :6817451  
##  thumbnail_link     comments_disabled  ratings_disabled   description       
##  Length:121399      Length:121399      Length:121399      Length:121399     
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
## 

El dataset usado, en ocasión del primer hito, corresponde a mx_dataset, el cual encapsula los videos más tendenciosos de YouTube en la región de México. Este dataset contiene, 121399 filas de información, dónde cada fila corresponde a los datos de un video que fue considerado para su captura debido a que estuvo en tendencia en algún momento de su existencia. Las columnas del dataset corresponde a:

unique(mx_dataset)

A continuación se cargará un segundo dataset asociado al anterior que contiene la información de las categorías de los videos:

library(jsonlite)
mx_list_categories <- fromJSON("./dataset/MX_category_id.json")
mx_categories <- data.frame(mx_list_categories)
head(mx_categories, n= 20)

El archivo MX_category_id.json contiene las categorías (categoryId) a la que puede pertenecer cada uno de los videos. Las columnas de este archivo son las siguientes:

Las dimensiones de este dataset son, 31 filas y 6 columnas.

dim(mx_categories)
## [1] 31  6

La columna items.snippet del dataset de categorías es de tipo data.frame, es decir, cada fila del conjunto contiene otro data.frame en el valor de la columna items.snippet.

class(mx_categories$items.snippet)
## [1] "data.frame"
head(mx_categories$items.snippet)

En total este dataset contiene 30 categorías, a continuación se listan todas las categorías:

unique(mx_categories$items.snippet$title)
##  [1] "Film & Animation"     "Autos & Vehicles"     "Music"               
##  [4] "Pets & Animals"       "Sports"               "Short Movies"        
##  [7] "Travel & Events"      "Gaming"               "Videoblogging"       
## [10] "People & Blogs"       "Comedy"               "Entertainment"       
## [13] "News & Politics"      "Howto & Style"        "Education"           
## [16] "Science & Technology" "Movies"               "Anime/Animation"     
## [19] "Action/Adventure"     "Classics"             "Documentary"         
## [22] "Drama"                "Family"               "Foreign"             
## [25] "Horror"               "Sci-Fi/Fantasy"       "Thriller"            
## [28] "Shorts"               "Shows"                "Trailers"

El dataset mx_dataset contiene valores nulos o en blanco en las columna description y tags. Se encontraron 6819 valores faltantes en la columna description y 20407 en la columna tags.

null_values_dataset <- sapply(mx_dataset, function(x) is.na(x) | x == "" | x == "[None]")
colSums(null_values_dataset)
##          video_id             title       publishedAt         channelId 
##                 0                 0                 0                 0 
##      channelTitle        categoryId     trending_date              tags 
##                 0                 0                 0             20407 
##        view_count             likes          dislikes     comment_count 
##                 0                 0                 0                 0 
##    thumbnail_link comments_disabled  ratings_disabled       description 
##                 0                 0                 0              6819

El dataset mx_categories no contiene valores nulos o en blanco en ninguna de sus columnas. Esto incluye las columnas que se encuentran dentro del dataframe de la columna items.snippet.

sapply(mx_categories, function(x) any(is.na(x) | x == ""))
##          kind          etag    items.kind    items.etag      items.id 
##         FALSE         FALSE         FALSE         FALSE         FALSE 
## items.snippet 
##         FALSE

Cantidad de videos por categoria

La cantidad de videos que tiene cada categoría para el dataset de México se presenta en el siguiente gráfico:

library(ggplot2)
aux_categories <- data.frame(categoryId = mx_categories$items.id , categoryTitle = mx_categories$items.snippet$title)
mx_categories <- merge(mx_dataset, aux_categories)

ggplot(mx_categories, aes(x = categoryTitle)) +
  geom_bar(stat = 'count') +
  coord_flip() +
  xlab("Categoria") + ylab("Cantidad de videos")

Cantidad de likes, dislikes y comentarios

Dentro del análisis exploratorio de los datos se contempla un análisis sobre los likes, dislikes y comentarios para el dataset de trendings de México.

Es importante mencionar que los análisis siguientes se realizaran en comparación a la cantidad de visitas de los videos, que cuentan con una media de 2.249.624 visitas.

mean(mx_dataset$view_count)
## [1] 2249624

Visitas vs likes

La cantidad de las visitas vs likes se presenta en el siguiente gráfico de disperción:

ggplot(mx_dataset, aes(x = view_count, y = likes)) +
  geom_point() +
  xlab("Cantidad de visitas") + ylab("Cantidad de likes")

Donde se aprecia que a medida que las visitas aumentan, la cantidad de likes tambien aumenta, y se percibe al observar el gráfico que su comportamiento podría ser lineal.

mean(mx_dataset$likes)
## [1] 160530.2

Es interesante mencionar además, que la cantidad de likes promedio para el caso de México es de 160.530 likes.

Visitas vs dislikes

La cantidad de las visitas vs dislikes se presenta en el siguiente gráfico de disperción:

ggplot(mx_dataset, aes(x = view_count, y = dislikes)) +
  geom_point() +
  xlab("Cantidad de visitas") + ylab("Cantidad de dislikes")

En este gráfico ocurre una situación interesante. Si bien a medida que los videos obtienen mayor vista tambien lo hacen los dislikes, se puede apreciar que la cantidad de dislikes oscina en la mitad de la muestra, y posteriormente se observa una baja de estos dislikes en los videos más vistos.

mean(mx_dataset$dislikes)
## [1] 2322.689

Es interesante mencionar además, que la cantidad de dislikes promedio para el caso de México es de 2.322 likes, muy inferior a la cantidad de likes promedio.

Visitas vs comentarios

La cantidad de visitas vs cantidad de comentarios se presenta de la siguiente manera:

ggplot(mx_dataset, aes(x = view_count, y = comment_count)) +
  geom_point() +
  xlab("Cantidad de visitas") + ylab("Cantidad de comentarios")

Para este caso, la cantidad de comentarios oscila en mayor medida que en los casos anteriores en la mitad de la muestra, no obteniendo un patrón claro, pero a medida que la cantidad de vistas aumenta, la cantidad de comentarios también lo hacen, observablemente en el gráfico, de manera lineal.

mean(mx_dataset$comment_count)
## [1] 11987.66

Para el caso de los comentarios, el promedio de estos es de 11,987 comentarios. Una cantidad superior a la de dislikes promedios, pero inferior a la de likes promedios.

Comparativa de canales

A continuación se realizará un análisis a los 10 canales con mayor cantidad de videos en la lista de trendings para el dataset de trendings de México.

Videos en la lista de trendings

Gráfico de top 10 canales con mas videos en la lista de trendings:

library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.1 ──
## ✓ tibble  3.1.6     ✓ dplyr   1.0.8
## ✓ tidyr   1.2.0     ✓ stringr 1.4.0
## ✓ readr   2.1.2     ✓ forcats 0.5.1
## ✓ purrr   0.3.4
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter()  masks stats::filter()
## x purrr::flatten() masks jsonlite::flatten()
## x dplyr::lag()     masks stats::lag()
top_10 <- group_by(mx_dataset, channelTitle) |>
  summarize(Freq = n()) |>
  arrange(desc(Freq)) |>
  top_n(10)
## Selecting by Freq
top_10
ggplot(top_10, aes(x = reorder(channelTitle, Freq), y = Freq)) +
  geom_bar(stat = 'identity') +
  coord_flip() +
  xlab('Canal de YouTube') +
  ylab('Cantidad de videos en trendings')

Likes y dislikes de videos en trendings

Gráfico de acumulacion de cantidad de likes y dislikes del top 10 canales con mas videos en trendings:

library(gridExtra)
## 
## Attaching package: 'gridExtra'
## The following object is masked from 'package:dplyr':
## 
##     combine
library("scales")
## 
## Attaching package: 'scales'
## The following object is masked from 'package:purrr':
## 
##     discard
## The following object is masked from 'package:readr':
## 
##     col_factor
top_10_accumulations <- group_by(mx_dataset, channelTitle) |>
  summarize(Freq = n(), likes = sum(likes), dislikes = sum(dislikes)) |>
  arrange(desc(Freq)) |>
  top_n(10, Freq)

likes_plot <- ggplot(top_10_accumulations,aes(x = reorder(channelTitle, Freq),y = likes)) + 
  geom_bar(stat = 'identity') + 
  coord_flip() +
  scale_y_continuous(labels = scales::comma, breaks = c(0, 245000000, 490000000, 735000000, 980000000)) +
  xlab("Canal") + ylab("Cantidad de likes")

dislikes_plot <- ggplot(top_10_accumulations,aes(x = reorder(channelTitle, Freq),y = dislikes)) + 
  geom_bar(stat = 'identity') + 
  coord_flip() +
  scale_y_continuous(labels = scales::comma) +
  xlab("Canal") + ylab("Cantidad de dislikes")


grid.arrange(likes_plot, dislikes_plot)

Mayor cantidad de likes

Gráfico de top 10 canales con mayor acumulación de likes:

likes_accumulation <- group_by(mx_dataset, channelTitle) |>
  summarize(Accumulation = sum(likes)) |>
  arrange(desc(Accumulation)) |>
  top_n(10)
## Selecting by Accumulation
ggplot(likes_accumulation, aes(x = reorder(channelTitle, Accumulation), y = Accumulation)) +
  geom_bar(stat = 'identity') +
  coord_flip() +
  xlab('Canal de YouTube') +
  ylab('Cantidad de videos en trendings')

Matriz de correlación

Matriz de correlación entre columnas para el dataset de trendings de México.

library(corrplot)
## corrplot 0.92 loaded
mx_dataset$comments_disabled <- as.numeric(as.logical(mx_dataset$comments_disabled))
mx_dataset$ratings_disabled <- as.numeric(as.logical(mx_dataset$ratings_disabled))

numeric_mx_dataset <- Filter(is.numeric, mx_dataset)
numeric_mx_dataset.cor <- cor(numeric_mx_dataset)
corrplot(numeric_mx_dataset.cor, method = 'number')

# mx_dataset <- read.csv("./dataset/MX_youtube_trending_data.csv", encoding = "UTF-8")
# mx_dataset$country <- "MX"
# us_dataset <- read.csv("./dataset/US_youtube_trending_data.csv", encoding = "UTF-8")
# us_dataset$country <- "US"
# br_dataset <- read.csv("./dataset/BR_youtube_trending_data.csv", encoding = "UTF-8")
# br_dataset$country <- "BR"
# ca_dataset <- read.csv("./dataset/CA_youtube_trending_data.csv", encoding = "UTF-8")
# ca_dataset$country <- "CA"
# de_dataset <- read.csv("./dataset/DE_youtube_trending_data.csv", encoding = "UTF-8")
# de_dataset$country <- "DE"
# fr_dataset <- read.csv("./dataset/FR_youtube_trending_data.csv", encoding = "UTF-8")
# fr_dataset$country <- "FR"
# gb_dataset <- read.csv("./dataset/GB_youtube_trending_data.csv", encoding = "UTF-8")
# gb_dataset$country <- "BG"
# in_dataset <- read.csv("./dataset/IN_youtube_trending_data.csv", encoding = "UTF-8")
# in_dataset$country <- "IN"
# jp_dataset <- read.csv("./dataset/JP_youtube_trending_data.csv", encoding = "UTF-8")
# jp_dataset$country <- "JP"
# kr_dataset <- read.csv("./dataset/KR_youtube_trending_data.csv", encoding = "UTF-8")
# kr_dataset$country <- "KR"
# ru_dataset <- read.csv("./dataset/RU_youtube_trending_data.csv", encoding = "UTF-8")
# ru_dataset$country <- "RU"
 
# dataset <- rbind(mx_dataset, us_dataset, br_dataset, ca_dataset, de_dataset, fr_dataset, gb_dataset, in_dataset, jp_dataset, kr_dataset, ru_dataset)

Análisis comparativo con los demás paises

Si bien el análisis exploratorio inicial se realizó tomando el dataset correspondiente a México, existen muchos otros paises dentro del dataset de trendings de Youtube, por lo cual se realizan algunos análisis generales a continuación.

Cantidad de visitas por pais

La cantidad de visitas de todos los videos en la lista de trendings por pais se presenta en el siguiente gráfico:

# view_count <- group_by(dataset, country) |>
#   summarize(views = sum(view_count))
 
# ggplot(view_count, aes(x = country, y = views)) +
#   geom_bar(stat = 'identity') +
#   scale_y_continuous(labels = scales::comma) +
#   xlab("Pais") + ylab("Cantidad de visitas")

Preguntas y problemas

Repositorio GitHub

El proyecto se documenta en un repositorio de GitHub, donde se podrá acceder en el siguiente link:

Repositorio de Github

Referencias

[1] https://support.google.com/youtube/answer/7239739?hl=es-419